package edg.db;

import java.sql.Statement;
import java.sql.ResultSet;

public class SimulationRun {
	
	private int runId;
	private String name;
	
	private SimulationRunResults results;
	
	/**
	 * Get all run IDs associated with a particular user.
	 * @param userId User ID you want run IDs for.
	 * @return Array of run IDs for given user.
	 */
	public static int[] getRunIds(int userId) {		
		Statement statement = Database.query(
				
				"SELECT id " +
				"FROM runs " +
				"WHERE " +
					"user_id=" + userId + " " +
				"ORDER BY started DESC;"
				
			);
		
		// We don't know how many results there are, so loop through once to
		// find out.
		int count = 0;
		try {
			while(statement.getResultSet().next()) {
				count++;
			}
		}
		catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
		
		int[] userIds = new int[count];
		count = 0;
		try {
			statement.getResultSet().first(); // Reset cursor
			do {
				userIds[count++] = statement.getResultSet().getInt("id");
			} while(statement.getResultSet().next());
		}
		catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
		
		return userIds;
	}
	
	/**
	 * Instantiate a single run so you can access its data.
	 * @param runId ID of the run you want to instantiate.
	 */
	public SimulationRun(int runId) {
		this.runId = runId;
		
		Statement statement = Database.query(
				
				"SELECT * " +
				"FROM runs_summary " +
				"WHERE " +
					"id=" + runId + " " +
				"LIMIT 1;"
				
			);
		
		Statement statement2 = Database.query(
				
				"SELECT * " +
				"FROM cms INNER JOIN runs ON cms.id = runs.cm_id " +
				"WHERE " +
					"runs.id=" + runId + " " +
				"LIMIT 1;"
				
			);
		
		try {
			statement.getResultSet().first();
			ResultSet result = statement.getResultSet();
			statement2.getResultSet().first();
			ResultSet result2 = statement2.getResultSet();
			
			name = result2.getString("name");
			
			results = new SimulationRunResults(
					new double[]{
							result.getDouble("triage_00"),
							result.getDouble("triage_25"),
							result.getDouble("triage_50"),
							result.getDouble("triage_75"),
							result.getDouble("triage_95"),
							result.getDouble("triage_100")
					}, new double[]{
							result.getDouble("treatment_00"),
							result.getDouble("treatment_25"),
							result.getDouble("treatment_50"),
							result.getDouble("treatment_75"),
							result.getDouble("treatment_95"),
							result.getDouble("treatment_100")
					}, new double[]{
							result.getDouble("acuity1_00"),
							result.getDouble("acuity1_25"),
							result.getDouble("acuity1_50"),
							result.getDouble("acuity1_75"),
							result.getDouble("acuity1_95"),
							result.getDouble("acuity1_100")
					}, new double[]{
							result.getDouble("acuity2_00"),
							result.getDouble("acuity2_25"),
							result.getDouble("acuity2_50"),
							result.getDouble("acuity2_75"),
							result.getDouble("acuity2_95"),
							result.getDouble("acuity2_100")
					}, new double[]{
							result.getDouble("acuity3_00"),
							result.getDouble("acuity3_25"),
							result.getDouble("acuity3_50"),
							result.getDouble("acuity3_75"),
							result.getDouble("acuity3_95"),
							result.getDouble("acuity3_100")
					}, new double[]{
							result.getDouble("acuity4_00"),
							result.getDouble("acuity4_25"),
							result.getDouble("acuity4_50"),
							result.getDouble("acuity4_75"),
							result.getDouble("acuity4_95"),
							result.getDouble("acuity4_100")
					}, new double[]{
							result.getDouble("acuity5_00"),
							result.getDouble("acuity5_25"),
							result.getDouble("acuity5_50"),
							result.getDouble("acuity5_75"),
							result.getDouble("acuity5_95"),
							result.getDouble("acuity5_100")
					}, new double[]{
							result.getDouble("acuity6_00"),
							result.getDouble("acuity6_25"),
							result.getDouble("acuity6_50"),
							result.getDouble("acuity6_75"),
							result.getDouble("acuity6_95"),
							result.getDouble("acuity6_100")
					}, new double[]{
							result.getDouble("util_doctors_00"),
							result.getDouble("util_doctors_25"),
							result.getDouble("util_doctors_50"),
							result.getDouble("util_doctors_75"),
							result.getDouble("util_doctors_95"),
							result.getDouble("util_doctors_100")
					}, new double[]{
							result.getDouble("util_nurses_00"),
							result.getDouble("util_nurses_25"),
							result.getDouble("util_nurses_50"),
							result.getDouble("util_nurses_75"),
							result.getDouble("util_nurses_95"),
							result.getDouble("util_nurses_100")
					}, new double[]{
							result.getDouble("util_triage_nurses_00"),
							result.getDouble("util_triage_nurses_25"),
							result.getDouble("util_triage_nurses_50"),
							result.getDouble("util_triage_nurses_75"),
							result.getDouble("util_triage_nurses_95"),
							result.getDouble("util_triage_nurses_100")
					}, new double[]{
							result.getDouble("util_clerks_00"),
							result.getDouble("util_clerks_25"),
							result.getDouble("util_clerks_50"),
							result.getDouble("util_clerks_75"),
							result.getDouble("util_clerks_95"),
							result.getDouble("util_clerks_100")
					}, new double[]{
							result.getDouble("util_beds_00"),
							result.getDouble("util_beds_25"),
							result.getDouble("util_beds_50"),
							result.getDouble("util_beds_75"),
							result.getDouble("util_beds_95"),
							result.getDouble("util_beds_100")
					}, result2.getInt("doctor"),
					result2.getInt("nurse"),
					result2.getInt("bed"),
					result2.getInt("rate")
					);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	/**
	 * Get the custom (optional) user-defined name of the run.
	 * @return Custom (optional) user-defined name of the run.
	 */
	public String getName() {
		return name;
	}
	
	/**
	 * Delete a run.
	 * @return Returns true if the run was successfully deleted.
	 */
	public boolean deleteRun() {
		Statement statement = Database.query(
				
				"DELETE " +
				"FROM runs " +
				"WHERE " +
					"id=" + runId + " " +
				"LIMIT 1;"
				
			);
		
		return statement != null;
	}
	
	/**
	 * Change the associated user of a run.  Should only be used to set a user
	 * ID in the case that an anonymous user runs a simulation and then
	 * registers while viewing the results.
	 * @param id ID of the user the run will now be associated with.
	 * @return Returns true if the ID of the associated user with the run was
	 * successfully changed.
	 */
	public boolean setRunUser(int id) {
			Statement statement = Database.query(
				
				"UPDATE runs " +
				"SET " +
					"user_id=" + id + " " +
				"WHERE " +
					"id=" + runId + " " +
				"LIMIT 1;"
				
			);
		
		return statement != null;
	}
	
	/**
	 * Get the summarized results of the run.
	 * @return A SimulationRunResults object which acts as a wrapper around all
	 * the results.
	 */
	public SimulationRunResults getResults() {
		return results;
	}
	
}